﻿using Microsoft.Extensions.Logging;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
using TcpJsonService.Core;

namespace TcpJsonService.Json
{
    /// <summary>
    /// 协议
    /// </summary>
    /// <typeparam name="T">参数类型</typeparam>
    public class Protocol<T>
    {
        /// <summary>
        /// 协议版本
        /// </summary>
        public string Version
        {
            get
            {
                return "1.0";
            }
        }

        /// <summary>
        /// 协议命令
        /// </summary>
        public string Cmd { get; set; }

        /// <summary>
        /// 参数
        /// </summary>
        public T Param { get; set; }
    }
    /// <summary>
    /// 控制协议参数
    /// </summary>
    public class LightControlParam
    {
        /// <summary>
        /// 模式 1待机模式 2示宽灯模式 3尾迹模式 4关灯
        /// </summary>
        public int Mode { get; set; }
        /// <summary>
        /// 频率 0-不闪烁 68 07 00 00 1-30Hz 68 07 68 07 2-60Hz 74 03 74 03 3-120Hz 7a 01 7a 01
        /// </summary>
        public int Freq { get; set; }
        /// <summary>
        /// 亮度 1~8级 对应14,1E,28,32,3C,46,50,5A
        /// </summary>
        public int Lightness { get; set; }
    }

    /// <summary>
    /// 响应协议参数
    /// </summary>
    public class AckParam
    {
        /// <summary>
        /// 错误代码
        /// </summary>
        public int ErrorCode { get; set; }

        /// <summary>
        /// 状态
        /// </summary>
        public string State
        {
            get
            {
                return ErrorCode switch
                {
                    0 => "ok",
                    -1 => "send failed",
                    -2 => "not found controller",
                    -3 => "unkown json",
                    -4 => "unkown cmd",
                    -5 => "unkown param",
                    _ => string.Empty,
                };
            }
        }

        /// <summary>
        /// 值
        /// </summary>
        public string Value { get; set; } = string.Empty;
    }

    /// <summary>
    /// 对外json通道
    /// </summary>
    /// <param name="port">本地监听端口</param>
    /// <param name="logger">日志</param>
    /// <param name="channel">控制器通道</param>
    public class JsonChannel(int port, ILogger logger, JsonControllerChannel channel) : TcpChannel(port, logger)
    {
        protected override bool Unpack(Socket socket, List<byte> buffer, ref int offset)
        {
            string requestJson = Encoding.UTF8.GetString(buffer.ToArray(), 0, buffer.Count);
            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true,
                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            };
            Protocol<AckParam> ackProtocol = new()
            {
                Param = new AckParam()
            };
            try
            {
                Protocol<object> header = JsonSerializer.Deserialize<Protocol<object>>(requestJson, options);
                if (string.IsNullOrEmpty(header.Cmd))
                {
                    ackProtocol.Param.ErrorCode = -4;
                }
                else
                {
                    ackProtocol.Cmd = $"{header.Cmd}Ack";
                    int port = ((IPEndPoint)socket.LocalEndPoint).Port;
                    if (header.Cmd == "LightControl")
                    {
                        Protocol<LightControlParam> p = JsonSerializer.Deserialize<Protocol<LightControlParam>>(requestJson, options);
                        if (p.Param == null)
                        {
                            ackProtocol.Param.ErrorCode = -5;
                        }
                        else
                        {
                            ackProtocol.Param.ErrorCode = channel.SendLightControl(port, p.Param.Mode, p.Param.Freq, p.Param.Lightness);
                        }
                    }
                    else if (header.Cmd == "GetWeatherInfo")
                    {
                        ControllerItem controller = channel.GetWeather(port);
                        if (controller == null)
                        {
                            ackProtocol.Param.ErrorCode = -2;
                        }
                        else
                        {
                            ackProtocol.Param.ErrorCode = 0;
                            ackProtocol.Param.Value = $"BG,/,/,RWIS,/,/,/,/,/,ABA,/,ACA,/,AQA,/,ADC,/,AEC,/,AFA,/,AMA,{controller.OneMinute},AMB,{controller.TenMinutes},ANA,{controller.Value},APH,/,APA,/,APD,/,APE,/,APF,/,APJ,/,ZAE,/,ZGA,/,ZFA,{controller.DeviceCode},ED";
                        }
                    }
                    else
                    {
                        ackProtocol.Param.ErrorCode = -4;
                    }
                }
            }
            catch (JsonException)
            {
                ackProtocol.Param.ErrorCode = -3;
            }
            string responseJson = JsonSerializer.Serialize(ackProtocol, options);
            byte[] responseBuffer = Encoding.UTF8.GetBytes(responseJson);
            bool result = Send(socket, responseBuffer);
            _logger.LogInformation($"json {socket.Handle} result:{result} code:{ackProtocol.Param.ErrorCode} value:{ackProtocol.Param.Value}\nrecv:\n{requestJson}\nsend:\n{responseJson}");
            offset += buffer.Count;
            return true;
        }
    }
}
